﻿using System;
using System.Reflection;
using WYJCore;
using WYJWeb;

namespace WYJData.Orm
{
    public class Column
    {
        public Column()
        {

        }
        public Column(ColumnAttribute attribute, PropertyInfo propertyInfo)
        {
            Attribute = attribute;
            ColumnInfo = propertyInfo;
            ColumnName = propertyInfo.Name;
            ColumnType = CheckType(propertyInfo.PropertyType);
        }

        private ColumnType CheckType(Type propertyType)
        {
            if (propertyType == typeof(string)) return ColumnType.String;
            if (propertyType == typeof(int)) return ColumnType.Int;
            if (propertyType == typeof(bool)) return ColumnType.Bool;
            if (propertyType == typeof(DateTime)) return ColumnType.Date;
            if (propertyType == typeof(DateTime?)) return ColumnType.Date;
            if (propertyType.IsEnum) return ColumnType.Enum;
            return ColumnType.Model;
        }

        public ColumnAttribute Attribute { get; set; }
        public PropertyInfo ColumnInfo { get; set; }
        public string ColumnName { get; set; }
        public ColumnType ColumnType { get; set; }
        public Table Table { get; set; }
        public int Ordinal { get; set; }

        /// <summary>
        /// 实体数据映射成表数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string TransValue(IModel data)
        {
            var realValue = ColumnInfo.GetValue(data);
            return ColumnType switch
            {
                ColumnType.Enum | ColumnType.Int => $"{(int)realValue}",
                ColumnType.Model => $"{((IModel)realValue)?.Id ?? 0}",
                _ => $"N'{realValue}'"
            };
        }

        /// <summary>
        /// 约束
        /// </summary>
        /// <returns></returns>
        public string GetConstraints()
        {
            var constraints = "";
            if (Attribute.IsPK) constraints += "PRIMARY KEY ";
            if (Attribute.Unique) constraints += "UNIQUE ";
            if (Attribute.Notnull) constraints += "NOT NULL ";
            if (Attribute.Identity) constraints += "IDENTITY ";
            return constraints;
        }

        public string CreateSql(string tableName, SqlClipType clipType = SqlClipType.Select)
        {
            return clipType switch
            {
                SqlClipType.Create => $"[{ColumnName}] {GetDataType()} {GetConstraints()}",
                SqlClipType.Query => $"{tableName}.[{ColumnName}]",
                _ => ColumnName,
            };
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetDataType()
        {
            var propertyType = ColumnInfo.PropertyType;
            if (propertyType.IsGenericType)
            {
                propertyType = propertyType.GetGenericArguments()[0];
            }
            //if(propertyType)
            if (propertyType == typeof(int) || propertyType.IsEnum || propertyType.IsModel())
            {
                return "INT";
            }
            else if (propertyType == typeof(bool))
            {
                return "BIT";
            }
            else if (propertyType == typeof(DateTime))
            {
                return "DateTime";
            }
            else
            {
                return "NVARCHAR(255)";
            }
        }

        public override string ToString()
        {
            return $"[{ColumnName}]";
        }

    }
}
